﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace CMS6Tools.Common
{
    public static class WebUtils
    {
        public const string ACCEPT_XML = "application/xml";
        public const string ACCEPT_JSON = "application/json";
        static readonly string DefaultUserAgent = "Mozilla/5.0 (Windows NT 5.1; rv:28.0) Gecko/20100101 Firefox/28.0";

        public static string DoPost(string url, IDictionary<string, string> parameters = null, string accept = ACCEPT_XML, NetworkCredential credential = null, IDictionary<string, string> headers = null)
        {
            parameters = parameters ?? new Dictionary<string, string>();
            headers = headers ?? new Dictionary<string, string>();
            var req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.KeepAlive = true;
            req.UserAgent = DefaultUserAgent;
            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
            req.Accept = accept;
            if (credential != null)
                req.Credentials = credential;

            foreach (var key in headers.Keys)
            {
                req.Headers[key] = headers[key];
            }

            var postData = Encoding.UTF8.GetBytes(BuildPostData(parameters));
            var reqStream = req.GetRequestStream();
            reqStream.Write(postData, 0, postData.Length);
            reqStream.Close();

            var rsp = (HttpWebResponse)req.GetResponse();
            var encoding = Encoding.GetEncoding(string.IsNullOrEmpty(rsp.CharacterSet) ? "utf-8" : rsp.CharacterSet);

            return GetResponseAsString(rsp, encoding);
        }

        public static string DoGet(string url, IDictionary<string, string> parameters = null, string accept = ACCEPT_XML, NetworkCredential credential = null, IDictionary<string, string> headers = null, Action<HttpWebRequest> requestAction = null)
        {
            parameters = parameters ?? new Dictionary<string, string>();
            headers = headers ?? new Dictionary<string, string>();
            if (parameters != null && parameters.Count > 0)
            {
                if (url.Contains("?"))
                {
                    url = url + "&" + BuildPostData(parameters);
                }
                else
                {
                    url = url + "?" + BuildPostData(parameters);
                }
            }

            var req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "GET";
            req.KeepAlive = true;
            req.UserAgent = DefaultUserAgent;
            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";

            req.Accept = accept;
            if (credential != null)
                req.Credentials = credential;

            if (requestAction != null)
                requestAction(req);

            foreach (var key in headers.Keys)
            {
                req.Headers[key] = headers[key];
            }
            var rsp = (HttpWebResponse)req.GetResponse();
            var encoding = Encoding.GetEncoding(string.IsNullOrEmpty(rsp.CharacterSet) ? "utf-8" : rsp.CharacterSet);
            return GetResponseAsString(rsp, encoding);
        }

        private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
        {
            var result = new StringBuilder();
            Stream stream = null;
            StreamReader reader = null;

            try
            {
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream, encoding);

                char[] buffer = new char[256];
                int readBytes = 0;
                while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    result.Append(buffer, 0, readBytes);
                }
            }
            finally
            {
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }

            return result.ToString();
        }

        private static string BuildPostData(IDictionary<string, string> parameters)
        {
            StringBuilder postData = new StringBuilder();
            bool hasParam = false;

            IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                string value = dem.Current.Value;
                if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
                {
                    if (hasParam)
                    {
                        postData.Append("&");
                    }

                    postData.Append(name);
                    postData.Append("=");
                    postData.Append(Uri.EscapeDataString(value));
                    hasParam = true;
                }
            }

            return postData.ToString();
        }
    }
}
